{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 10.4 Representing rooted trees"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-1\n",
    "\n",
    "> Draw the binary tree rooted at index 6 that is represented by the following attributes:\n",
    "\n",
    "> |index|key|left|right|\n",
    "|-|-|-|-|\n",
    "|1|12|7|3|\n",
    "|2|15|8|NIL|\n",
    "|3|4|10|NIL|\n",
    "|4|10|5|9|\n",
    "|5|2|NIL|NIL|\n",
    "|6|18|1|4|\n",
    "|7|7|NIL|NIL|\n",
    "|8|14|6|2|\n",
    "|9|21|NIL|NIL|\n",
    "|10|5|NIL|NIL|"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](img/10.4-1.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-2\n",
    "\n",
    "> Write an $O(n)$-time recursive procedure that, given an $n$-node binary tree, prints out the key of each node in the tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class TreeNode:\n",
    "    def __init__(self, value, left=None, right=None):\n",
    "        self.value = value\n",
    "        self.left = left\n",
    "        self.right = right\n",
    "\n",
    "\n",
    "def print_tree(node):\n",
    "    if node is not None:\n",
    "        print(node.value)\n",
    "        print_tree(node.left)\n",
    "        print_tree(node.right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-3\n",
    "\n",
    "> Write an O$(n)$-time nonrecursive procedure that, given an $n$-node binary tree, prints out the key of each node in the tree. Use a stack as an auxiliary data structure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "class TreeNode:\n",
    "    def __init__(self, value, left=None, right=None):\n",
    "        self.value = value\n",
    "        self.left = left\n",
    "        self.right = right\n",
    "\n",
    "\n",
    "def print_tree(node):\n",
    "    stack = [node]\n",
    "    while len(stack) > 0:\n",
    "        node = stack[-1]\n",
    "        del stack[-1]\n",
    "        if node is not None:\n",
    "            print(node.value)\n",
    "            stack.append(node.left)\n",
    "            stack.append(node.right)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-4\n",
    "\n",
    "> Write an $O(n)$-time procedure that prints all the keys of an arbitrary rooted tree with $n$ nodes, where the tree is stored using the left-child, right-sibling representation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "class TreeNode:\n",
    "    def __init__(self, value, parent=None, left=None, right=None):\n",
    "        self.value = value\n",
    "        self.parent = parent\n",
    "        self.left_child = left\n",
    "        self.right_sibling = right\n",
    "\n",
    "\n",
    "def print_tree(node):\n",
    "    if node is not None:\n",
    "        while node.parent is not None:\n",
    "            node = node.parent\n",
    "        while node is not None:\n",
    "            print(node.value)\n",
    "            sibling = node.right_sibling\n",
    "            while sibling is not None:\n",
    "                print(sibling.value)\n",
    "                sibling = sibling.right_sibling\n",
    "            node = node.left_child"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-5 $\\star$\n",
    "\n",
    "> Write an $O(n)$-time nonrecursive procedure that, given an $n$-node binary tree, prints out the key of each node. Use no more than constant extra space outside of the tree itself and do not modify the tree, even temporarily, during the procedure."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "class TreeNode:\n",
    "    def __init__(self, value, left=None, right=None):\n",
    "        self.value = value\n",
    "        self.parent = None\n",
    "        self.left = left\n",
    "        self.right = right\n",
    "        if left is not None:\n",
    "            left.parent = self\n",
    "        if right is not None:\n",
    "            right.parent = self\n",
    "\n",
    "\n",
    "def print_tree(node):\n",
    "    prev = None\n",
    "    while node is not None:\n",
    "        if node.parent == prev:\n",
    "            print(node.value)\n",
    "            prev = node\n",
    "            if node.left is None:\n",
    "                node = node.parent\n",
    "            else:\n",
    "                node = node.left\n",
    "        elif node.left == prev:\n",
    "            prev = node\n",
    "            if node.right is None:\n",
    "                node = node.parent\n",
    "            else:\n",
    "                node = node.right\n",
    "        else:\n",
    "            prev = node\n",
    "            node = node.parent"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 10.4-6 $\\star$\n",
    "\n",
    "> The left-child, right-sibling representation of an arbitrary rooted tree uses three pointers in each node: _left-child_, _right-sibling_, and _parent_. From any node, its parent can be reached and identified in constant time and all its children can be reached and identified in time linear in the number of children. Show how to use only two pointers and one boolean value in each node so that the parent of a node or all of its children can be reached and identified in time linear in the number of children."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Use boolean to identify the last sibling, and the last sibling's right-sibling points to the parent."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
